package top.cardone.data.jdbc.dao;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import top.cardone.context.ApplicationContextHolder;
import top.cardone.data.dao.PageDao;
import top.cardone.data.support.PageSupport;
import top.cardone.data.support.PageableSupport;

import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2015/8/26.
 */
public class PageJdbcDao extends SimpleJdbcDao implements PageDao {
    @Override
    public Page<Map<String, Object>> page(Object page) {
        String countSqlFilePath = this.getSqlFilePath("page.count");
        String findListSqlFilePath = this.getSqlFilePath("page.find");

        Map<String, Object> pageMap = this.toMap(page, "page");

        Map<String, Object> newPageMap = Maps.newHashMap();

        for (Map.Entry<String, Object> pageEntry : pageMap.entrySet()) {
            newPageMap.put("where_and_eq_" + pageEntry.getKey(), Boolean.TRUE.toString());
            newPageMap.put("where_and_eq_" + pageEntry.getKey() + "_value", pageEntry.getValue());
        }

        return this.page(countSqlFilePath, findListSqlFilePath, newPageMap);
    }

    protected Page<Map<String, Object>> page(String countSqlFilePath, String findListSqlFilePath, Map<String, ?> page) {
        final long totalSize = this.readOne(Long.class, countSqlFilePath, page);

        if (totalSize < 1) {
            return ApplicationContextHolder.func(PageSupport.class, pageSupport -> pageSupport.newPage(Lists.newArrayList(), page, totalSize));
        }

        Pageable pageable = ApplicationContextHolder.func(PageableSupport.class, pageableSupport -> pageableSupport.newPageable(page));

        Map<String, Object> newPage = Maps.newHashMap(page);

        newPage.put("pageNumber", pageable.getPageNumber());
        newPage.put("pageSize", pageable.getPageSize());
        newPage.put("offset", pageable.getOffset());

        List<Map<String, Object>> findList = this.findList(findListSqlFilePath, newPage);

        return ApplicationContextHolder.func(PageSupport.class, pageSupport -> pageSupport.newPage(findList, page, totalSize));
    }

    @Override
    public <P> Page<P> page(Class<P> mappedClass, Object page) {
        String countSqlFilePath = this.getSqlFilePath("page.count");
        String findListSqlFilePath = this.getSqlFilePath("page.find");

        Map<String, Object> pageMap = this.toMap(page, "page");

        Map<String, Object> newPageMap = Maps.newHashMap();

        for (Map.Entry<String, Object> pageEntry : pageMap.entrySet()) {
            newPageMap.put("where_and_eq_" + pageEntry.getKey(), Boolean.TRUE.toString());
            newPageMap.put("where_and_eq_" + pageEntry.getKey() + "_value", pageEntry.getValue());
        }

        return this.page(mappedClass, countSqlFilePath, findListSqlFilePath, newPageMap);
    }

    protected <P> Page<P> page(Class<P> mappedClass, String countSqlFilePath, String
            findListSqlFilePath, Map<String, ?> page) {
        final long totalSize = this.readOne(Long.class, countSqlFilePath, page);

        if (totalSize < 1) {
            return ApplicationContextHolder.func(PageSupport.class, pageSupport -> pageSupport.newPage(Lists.newArrayList(), page, totalSize));
        }

        Pageable pageable = ApplicationContextHolder.func(PageableSupport.class, pageableSupport -> pageableSupport.newPageable(page));

        Map<String, Object> newPage = Maps.newHashMap(page);

        newPage.put("pageNumber", pageable.getPageNumber());
        newPage.put("pageSize", pageable.getPageSize());
        newPage.put("offset", pageable.getOffset());

        List<P> findList = this.findList(mappedClass, findListSqlFilePath, newPage);

        return ApplicationContextHolder.func(PageSupport.class, pageSupport -> pageSupport.newPage(findList, page, totalSize));
    }
}